kexec: limit scope of the use of compat_kexec_range_t
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 28 Feb 2008 10:45:47 +0000 (10:45 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 28 Feb 2008 10:45:47 +0000 (10:45 +0000)
Unless I am mistaken, the compat functions are provided a stable ABI.
This includes providing a stable version of xen_kexec_range_t in the
form of compat_kexec_range_t.  However, internally it doesn't really
matter how xen represents the data.

Currently the code provides for the creation of a compat version of
all kexec range functions, which use the compat_kexec_range_t
function. This is difficult to extend if range code exists outside of
xen/common/kexec.c.

The existence of "#ifdef CONFIG_X86_64" in the code suggests that some
of the range code might be better off in architecture specific code.
Furthermore, subsequent patches will introduce ia64-specific range
handling code, which really would be much better off somewhere in
arch/ia64/.

With this in mind, the handling of compat_kexec_range_t is changed
such that the code which reads and returns data from user-space
translates between compat_kexec_range_t and xen_kexec_range_t.  As,
padding aside, the two structures are currently the same this is quite
easy. Things may get more tricky in the future, but I don't believe
this change is likely to make things significantly worse (or better)
in that regard. In any case, refactoring can occur again as required.

Signed-off-by: Simon Horman <horms@verge.net.au>
xen/common/compat/kexec.c
xen/common/kexec.c

index b167d8a4ff76f74f0eb39f9c4a3165247d32defd..bcf9d05908586554efc13540bfbe0ed9ade62d29 100644 (file)
@@ -9,11 +9,6 @@
 
 #define do_kexec_op compat_kexec_op
 
-#undef kexec_get
-#define kexec_get(x)      compat_kexec_get_##x
-#define xen_kexec_range   compat_kexec_range
-#define xen_kexec_range_t compat_kexec_range_t
-
 #define kexec_load_unload compat_kexec_load_unload
 #define xen_kexec_load    compat_kexec_load
 #define xen_kexec_load_t  compat_kexec_load_t
index 4e95cf319d444a4a9e5b7f9d3d5e71afa4703c5a..f1aa784e93803a636befa6482f72c0c36c288a24 100644 (file)
@@ -153,11 +153,7 @@ static int sizeof_note(const char *name, int descsz)
             ELFNOTE_ALIGN(descsz));
 }
 
-#define kexec_get(x)      kexec_get_##x
-
-#endif
-
-static int kexec_get(reserve)(xen_kexec_range_t *range)
+static int kexec_get_reserve(xen_kexec_range_t *range)
 {
     if ( kexec_crash_area.size > 0 && kexec_crash_area.start > 0) {
         range->start = kexec_crash_area.start;
@@ -168,7 +164,7 @@ static int kexec_get(reserve)(xen_kexec_range_t *range)
     return 0;
 }
 
-static int kexec_get(xen)(xen_kexec_range_t *range)
+static int kexec_get_xen(xen_kexec_range_t *range)
 {
 #ifdef CONFIG_X86_64
     range->start = xenheap_phys_start;
@@ -179,7 +175,7 @@ static int kexec_get(xen)(xen_kexec_range_t *range)
     return 0;
 }
 
-static int kexec_get(cpu)(xen_kexec_range_t *range)
+static int kexec_get_cpu(xen_kexec_range_t *range)
 {
     int nr = range->nr;
     int nr_bytes = 0;
@@ -223,33 +219,78 @@ static int kexec_get(cpu)(xen_kexec_range_t *range)
     return 0;
 }
 
-static int kexec_get(range)(XEN_GUEST_HANDLE(void) uarg)
+static int kexec_get_range_internal(xen_kexec_range_t *range)
 {
-    xen_kexec_range_t range;
     int ret = -EINVAL;
 
-    if ( unlikely(copy_from_guest(&range, uarg, 1)) )
-        return -EFAULT;
-
-    switch ( range.range )
+    switch ( range->range )
     {
     case KEXEC_RANGE_MA_CRASH:
-        ret = kexec_get(reserve)(&range);
+        ret = kexec_get_reserve(range);
         break;
     case KEXEC_RANGE_MA_XEN:
-        ret = kexec_get(xen)(&range);
+        ret = kexec_get_xen(range);
         break;
     case KEXEC_RANGE_MA_CPU:
-        ret = kexec_get(cpu)(&range);
+        ret = kexec_get_cpu(range);
         break;
     }
 
+    return ret;
+}
+
+static int kexec_get_range(XEN_GUEST_HANDLE(void) uarg)
+{
+    xen_kexec_range_t range;
+    int ret = -EINVAL;
+
+    if ( unlikely(copy_from_guest(&range, uarg, 1)) )
+        return -EFAULT;
+
+    ret = kexec_get_range_internal(&range);
+
     if ( ret == 0 && unlikely(copy_to_guest(uarg, &range, 1)) )
         return -EFAULT;
 
     return ret;
 }
 
+#else /* COMPAT */
+
+#ifdef CONFIG_COMPAT
+static int kexec_get_range_compat(XEN_GUEST_HANDLE(void) uarg)
+{
+    xen_kexec_range_t range;
+    compat_kexec_range_t compat_range;
+    int ret = -EINVAL;
+
+    if ( unlikely(copy_from_guest(&compat_range, uarg, 1)) )
+        return -EFAULT;
+
+    range.range = compat_range.range;
+    range.nr = compat_range.nr;
+    range.size = compat_range.size;
+    range.start = compat_range.start;
+
+    ret = kexec_get_range_internal(&range);
+
+    if ( ret == 0 ) {
+        range.range = compat_range.range;
+        range.nr = compat_range.nr;
+        range.size = compat_range.size;
+        range.start = compat_range.start;
+
+        if ( unlikely(copy_to_guest(uarg, &compat_range, 1)) )
+             return -EFAULT;
+    }
+
+    return ret;
+}
+#endif /* CONFIG_COMPAT */
+
+#endif /* COMPAT */
+
+
 #ifndef COMPAT
 
 static int kexec_load_get_bits(int type, int *base, int *bit)
@@ -375,7 +416,11 @@ ret_t do_kexec_op(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
     switch ( op )
     {
     case KEXEC_CMD_kexec_get_range:
-        ret = kexec_get(range)(uarg);
+#ifndef COMPAT
+        ret = kexec_get_range(uarg);
+#else
+        ret = kexec_get_range_compat(uarg);
+#endif
         break;
     case KEXEC_CMD_kexec_load:
     case KEXEC_CMD_kexec_unload: